package com.ofek.applicationbase.utils;

/**
 * Synchronized Semaphore
 * @author Ofek
 *
 */
public class Semaphore {	
	private int i;
	private final Object lock = new Object();

	public Semaphore(final int init) {
		i=init;
	}

	public void await() {

		synchronized (lock) {
			if (--i>=0) return;
			System.out.println(Thread.currentThread().getName()+" is Going to sleep for a while.");
			try {
				lock.wait();
			} catch (final InterruptedException e) {
				System.out.println("Semaphored Thread was interrupted.");
				e.printStackTrace();
			}
			System.out.println("Wakey wakey "+Thread.currentThread().getName()+" rise and shine!");
		}
	}
	/**
	 * increment without notify
	 */
	public void increment() {
		synchronized (lock) {
			++i;
		}
	}
	/**
	 * decrement without waiting
	 */
	public void decrement() {
		synchronized (lock) {
			--i;
		}
	}
	public void signal() {
		synchronized (lock) {
			if (++i>0) return;
			lock.notify();
		}
	}
	public void signal(final int n) {
		for (int i=0;i<n;i++) signal();
	}
	public int count() {
		synchronized (lock) {
			return -i;
		}
	}

	public void release() {
		synchronized (lock) {
			while (i<0) signal();
		}
	}

	public Object getLock() {
		return lock;
	}
}
